<?php

abstract class Handler_CreateItem extends Handler_Item
{
	protected $m_tdi;
	protected $m_oi;
	protected $fc;
	protected $view;

	protected $process_form;
	protected $process_type = NULL;


	public function init() {
		$this->aa = $this->module->aa;
		$this->rh->UseClass("Form_Form");

		$this->ctx->mm->setAclAssistant($this->aa);
		$this->m_tdi = $this->rh->ctx->mm->getModel("Tdi", "m");
		$this->m_oi = $this->ctx->mm->getModel("OpenId", "m");

		$this->rh->useClass("Handler_FormCreator");
		$this->fc = new FormCreator($this->rh);

		$this->rh->UseClass("RL_URLGenerator");
	}

	protected function getDoctypesOptions() {
		// генерирурем типы документов
		$ug = new RL_URLGenerator($this->rh->router->getRule('createitem_type'));
		$ug->setRouter($this->rh->router);

		if ( isset($this->aa->acl_data) && !empty($this->aa->acl_data)
		&& isset($this->aa->acl_data['tdi_url']) && !empty($this->aa->acl_data['tdi_url']) ) {
			$this->params['tdi_url'] = $this->aa->acl_data['tdi_url'];
		} else {
			$this->params['tdi_url'] = '';
		}

		foreach ($this->ctx->doctypes as $type_key=>$type_config) {
			$this->params["doctype_url"] = $type_key;
			$ug->setParams($this->params);

			$doctypes_options[$type_key] = array(
			"title"=>$type_config['typename'],
			"color"=>$this->m_tdi->getColorForType($type_key),
			"link"=>$ug->generateUrl(),

			);
		}
		return $doctypes_options;
	}

	protected function determineProcessType($force_type=NULL) {
		if ($force_type) {
			$this->process_type = $force_type;
			return;
		}
		// определяем тип который нужно вывести в текущем запросе
		if (isset($this->params['doctype_url']) && isset($this->ctx->doctypes[$this->params['doctype_url']])) {
			$this->process_type = $this->params['doctype_url'];
		} else {
			$this->process_type = key($this->ctx->doctypes);
		}

	}


	protected function createForm() {
		// создаст объект форм для каждого раздела, на входе массив с разделами + массив с типами документов
		if ($this->process_type) {
			$dname = $this->process_type;
			$dtype = $this->ctx->doctypes[$this->process_type];
		} else {
			reset($this->ctx->doctypes);
			$dname = key($this->ctx->doctypes);
			$dtype = current($this->ctx->doctypes);
		}
		$this->fc->setSections($this->getSectionsForType($dname));

		if ( isset($this->aa->acl_data['tdi']->data['tags']) ) {
			$tags = $this->aa->acl_data['tdi']->data['tags'];
		} else {
			$tags= '';
		}

		$this->fc->setParams($dname, $dname, $tags, $this->m_tdi->getColorForType($this->process_type), $this->aa->acl_data['comity_oid'], $dtype['fields'], $this->ctx->system_fields);

		if ( isset($this->aa->acl_data['tdi_url']) && !empty($this->aa->acl_data['tdi_url'])
		&& isset($this->aa->acl_data['tdi_oid']) && !empty($this->aa->acl_data['tdi_oid']) ) {
			$this->fc->setData(array('tdi_oid'=>$this->aa->acl_data['tdi_oid']));
		}

		$form = $this->fc->createForm();

		$this->process_form = $form;
		$this->process_type = $dname;

	}


	public function getSectionsForType($type_name=NULL) {
		// накопим в $sections только те разделы куда можно писать
		$sections = array();
		$tdi_oids = array();
		foreach ($this->aa->acl_data['tdi_list'] as $tdi) $tdi_oids[] = $tdi['id_object'];
		foreach ($this->m_tdi->getSections( $tdi_oids, false ) as $oid=>$tdi_content) {
			// проверим доступ к разделу
			$this->aa->getAvailableOperations( $oid );
			if ($this->aa->is_granted(array('item_create', 'item_create_premod'))) {
				/*
				if ($tdi_content['itype'] == $type_name)
				$sections[$oid] = $tdi_content['title'];
				*/
				$sections[$oid] = $tdi_content['title'];
			}
		}
		$sections[0] = "Без раздела";
		return $sections;
	}

	/**
	 * Обновить итем.
	 *
	 * @return void
	 * @author Alexander Sibiryakov
	 **/
	public function upItem( $objtype_name, $item_oid, array $doctype, array $field_values ) {
		$m_item = $this->getModel($objtype_name);
		$object = $m_item->getItem( $item_oid );

		$object = $this->processData($object, $doctype, $field_values);
		if ($object instanceof fobject) {
			return $m_item->upItem($object);
		} return $object;

	}

	/**
	 * Создает итем. Берет описание типа и массив значений.
	 *
	 * TODO: Сделать обработку ошибок при помощи исчключений, потому что сейчас вовсе не очевидно
	 * кто и где и при каких условиях сделает откат транзакции. Да и вообще привязывать подобную обработку к типу в
	 * языке с динамической типизацией мне кажется не надежно.
	 *
	 * @return fobject или string
	 * @author Alexander Sibiryakov
	 **/
	public function createItem($objtype_name, array $doctype, array $field_values, $parent_oid) {

		// стратегия такая: сперва создадим объект, чтобы можно было делать модификации в базе уже имея id-шник,
		// а затем после модификаций пересохраним объект с обработанным данными
		$m_item = $this->getModel($objtype_name);
		//$this->rh->UseClass("Handler_ModelFieldProcessor");
		$obj = $m_item->createItem($objtype_name);
		$res = $obj->save();

		// если эта штука вернет объект типа отличного от fobject то метод process() сделает откат транзакции
		$result = $this->processData($obj, $doctype, $field_values);
		// FIXIT : 2008-06-17 : lucky
		// неявный факт:
		// когда все хорошо, $result это $obj
		// когда все плохо,  $result это что-то другое (текст с ошибкой).
		if ($result instanceof fobject) {
			if ($m_item->saveItem($obj, $parent_oid)) {
				return $obj;
			} else {
				return $m_item->error;
			}
		} else {
			return $result; // там должен быть текст с ошибкой
		}

	}

	public function setupView($name = "create") {
		$this->view = $this->rh->views->findByName($name);
		$this->view->data = $this->aa->template_data;
	}

	public function setViewVar($key, $value) {
		$this->view->data[$key] = $value;
	}

	public function typeTransform($type) {
		return substr($type, 1);

	}

	private function getModel($objtype_name) {
		$this->rh->useClass("Model_Item");
		switch($objtype_name) {
			case "vote":
				$m = $this->rh->ctx->mm->getModel("Vote", "m");
				break;

			case "rss_rule":
				$m = $this->rh->ctx->mm->getModel("RssRule", "m");
				break;

			default:
				$m = $this->rh->ctx->mm->getModel("Item", "m");
				break;
		}
		return $m;
	}

	private function processData(fobject $obj, array $fields, array $field_values) {

		$data = $obj->data; // создаем структуру данных, запуская обработчик формы на каждом поле

		$this->rh->UseClass("Handler_ModelFieldProcessor");
		$processor = new Model_Field_Processor( $this->rh, $this->aa, $obj->id );

		foreach ($field_values as $field_name=>$value) {
			$field_config = $fields[$field_name];

			if (isset($field_config['db_name'])) {
				$key = $field_config['db_name'];
			} else $key = $field_name;

			if ( (isset($data[$field_name])) && (isset($field_config['not_editable'])) ) continue;  // если поле не редактируемое, и собираемся перезаписать

			if (isset($field_config["external_postprocessing"])) {
				// требуется специфическая обработка поля

				$result = $processor->processField($field_config, $field_name, $field_values[$field_name]);

				if ($result === false) {
					$error .= $processor->error_msg()."<br />";
				} else {
					$prs = $processor->getResults();
					if (is_array($prs)) {
						$data = array_merge($data, $prs);
					}
					$processor->cleanResults();
					//$data[ $key ] = $processor->get_last_result( $field_name );
				}

			} else {
				// просто скопировать значение
				$data[ $key ] = $value;
			}

		}
		//var_dump($data); die();

		$this->rh->UseClass('RL_CyrDate');
		$data[ 'date' ] = RL_CyrDate::newNow()->format("%Y-%m-%d %H:%i:%s");

		$obj->data = $data;
		if ($error) {
			return $error;
		} else return $obj;

	}

	public function redirectToItem ($msg='', $o_item = NULL)
	{
		if ($msg) {
			$this->rh->setMessage($msg);
		}
		// для проголосовавших редирект на страницу итема
		$this->rh->UseClass('RL_URLGenerator');
		$ug = new RL_URLGenerator($this->rh->router->getRule('showitem'));
		$ug->setRouter($this->rh->router);
		$ug->setParams(array(
		'community_url' => $this->params['community_url'],
		'id_item' => $o_item ? $o_item->id : $this->params['id_item'],
		));
		$url = $ug->generateUrl();
		if ($url) {
			$this->rh->redirect($url);
		} else {
			$this->rh->response->setContent( "Wazzup?!" );
		}
	} // end of method redirectToItem
}
